package com.cngphone.AnFetion.Fetion;

import java.io.InputStream;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import com.cngphone.AnFetion.FetionUri;
import com.cngphone.AnFetion.Settings;
import com.cngphone.AnFetion.tools.LogUtil;
public class SsiAppSignin extends FetionBase {
    private static final String TAG = "SsiAppSignin";
    
    private String ssiAppSigninUrl;

    public String getSsiAppSigninUrl() {
        return ssiAppSigninUrl;
    }

    public void setSsiAppSigninUrl(String ssiAppSigninUrl) {
        this.ssiAppSigninUrl = ssiAppSigninUrl;
    }

    private String mobileno;

    public String getMobileno() {
        return mobileno;
    }

    public void setMobileno(String mobileno) {
        this.mobileno = mobileno;
    }

    private String passwordDigest;

    public SsiAppSignin(String ssiAppSigninUrl, String mobileno, String passwordDigest) {
        this.ssiAppSigninUrl = ssiAppSigninUrl;
        this.mobileno = mobileno;
        this.passwordDigest = passwordDigest;
    }

    private String ssicCookie;

    public String getSsicCookie() {
        return ssicCookie;
    }

    private FetionUri uri;

    public FetionUri getUri() {
        return uri;
    }

    public void setUri(FetionUri uri) {
        this.uri = uri;
    }

    public String getUserStatus() {
        return userStatus;
    }

    public void setUserStatus(String userStatus) {
        this.userStatus = userStatus;
    }

    private String userStatus;

    public void setSsicCookie(String ssicCookie) {
        Pattern pattern = Pattern.compile("ssic=(.*?);");
        Matcher matcher;
        try {
            matcher = pattern.matcher(ssicCookie);
            if (!matcher.find()) {
                LogUtil.w(TAG, "can't find ssic in " + ssicCookie);
                return;
            }
            ssicCookie = matcher.group(1);
        } catch (Exception e1) {
            e1.printStackTrace();
            return;
        }
        this.ssicCookie = ssicCookie;
    }

    private int userID;

    public int getUserID() {
        return userID;
    }

    public void setUserID(int userID) {
        this.userID = userID;
    }

    private TrustManager[] tm = { new X509TrustManager() {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[] {};
        }

    } };
    private HostnameVerifier hostnameVerifier = new HostnameVerifier() {

        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

    @Override
    public boolean execute() {
        this.onStatusChanged(StatusDefine.EMPTY, StatusDefine.SSIAPPSIGNINING);
        try {
            SSLContext sslContext = SSLContext.getInstance("TLS");
            // Provider p = Provider.Service;

            sslContext.init(null, tm, new java.security.SecureRandom());

            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            // 创建URL对象
            URL myURL = new URL(this.getSsiAppSigninUrl() + "?mobileno=" + String.valueOf(this.mobileno)
                    + "&digest=" + this.passwordDigest);

            HttpsURLConnection.setDefaultSSLSocketFactory(ssf);
            HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);

            // 创建HttpsURLConnection对象，并设置其SSLSocketFactory对象
            HttpsURLConnection httpsConn = (HttpsURLConnection) myURL.openConnection();
            httpsConn.connect();

            if (httpsConn.getResponseCode() != 200) {
                if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(),
                        "System returned error when ssiappsignin, the error code is:"
                                + httpsConn.getResponseCode());
                if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(), "The error info is"
                        + httpsConn.getResponseMessage());
                this.onSetText("System returned error when ssiappsignin. The error code is:"
                        + httpsConn.getResponseCode() + ". And the error info is "
                        + httpsConn.getResponseMessage());
                this.onStatusChanged(StatusDefine.SSIAPPSIGNINING, StatusDefine.GETSYSTEMCONFIGOK);
                return false;
            }

            InputStream stream = httpsConn.getInputStream(); // Tiger. Move here.

            this.setSsicCookie(httpsConn.getHeaderField("set-cookie"));
            // System.out.println(ssicCookie);
            String contentLength = httpsConn.getHeaderField("content-length");
            String str = "";
            if (!contentLength.equals("")) {
                byte[] data = new byte[Integer.valueOf(contentLength)];
                int count = stream.read(data);
                while (count < data.length) {
                    int read = stream.read(data, count, data.length - count);
                    count += read > -1 ? read : 0;
                }
                str = new String(data);

            }
            stream.close();
            Document doc = parseXmlDocument(str);
            
            Element results = doc.getDocumentElement();
            if (results == null || !results.getNodeName().equals("results")) {
                if (Settings.DEBUG) LogUtil.i(SystemConfig.class.getSimpleName(),
                        "The config file gained error when ssiappsignin.");
                if (Settings.DEBUG) LogUtil.i(SystemConfig.class.getSimpleName(), str);
                this.onSetText("The config file gained error when ssiappsignin.");
                this.onStatusChanged(StatusDefine.SSIAPPSIGNINING, StatusDefine.GETSYSTEMCONFIGOK);
                return false;
            } else if (results.getAttributeNode("status-code") != null
                    && !results.getAttributeNode("status-code").getNodeValue().equals("200")) {
                if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(),
                        "System returned error when ssiappsignin, the error code is:"
                                + httpsConn.getResponseCode());
                this.onSetText("System returned error when ssiappsignin");
                this.onStatusChanged(StatusDefine.SSIAPPSIGNINING, StatusDefine.GETSYSTEMCONFIGOK);
                return false;
            } else {
                NodeList user = results.getElementsByTagName("user");
                if (user.getLength() == 1) {
                    Element userElement = (Element) user.item(0);
                    if (userElement.getAttributeNode("mobile-no") != null
                            && userElement.getAttributeNode("mobile-no").getNodeValue().equals(this.mobileno)) {
                        this.setUri(new FetionUri(userElement.getAttributeNode("uri").getNodeValue()));
                        this.setUserStatus(userElement.getAttributeNode("user-status").getNodeValue());
                        this.setUserID(Integer.parseInt(userElement.getAttributeNode("user-id")
                                .getNodeValue()));
                        this.onSetText("ssiappsignin OK");
                        this.onStatusChanged(StatusDefine.SSIAPPSIGNINING, StatusDefine.SSIAPPSIGNINIED);
                        return true;
                    } else {
                        if (Settings.DEBUG) LogUtil
                                .d(SystemConfig.class.getSimpleName(),
                                        "The mobile No. returned by system when ssiappsignin is not the same with the one commited.");
                        if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(), str);
                        this
                                .onSetText("The mobile No. returned by system when ssiappsignin is not the same with the one commited.");
                        this.onStatusChanged(StatusDefine.SSIAPPSIGNINING, StatusDefine.GETSYSTEMCONFIGOK);
                        return false;
                    }
                } else {
                    if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(),
                            "User segments were more than one when ssiappsignin");
                    if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(), str);
                    this.onSetText("System returned error when ssiappsignin");
                    this.onStatusChanged(StatusDefine.SSIAPPSIGNINING, StatusDefine.GETSYSTEMCONFIGOK);
                    return false;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(),
                    "The config file gained error when ssiappsignin.");
            if (Settings.DEBUG) LogUtil.d(SystemConfig.class.getSimpleName(), e.getMessage());
            this.onSetText(e.toString() + "(when ssiappsignin)");
            this.onStatusChanged(StatusDefine.SSIAPPSIGNINING, StatusDefine.GETSYSTEMCONFIGOK);
            return false;
        }
    }

}
